hvm: More cleanups around paging interfaces.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 8 Aug 2007 09:34:03 +0000 (10:34 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 8 Aug 2007 09:34:03 +0000 (10:34 +0100)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/mm/hap/hap.c
xen/include/asm-x86/hvm/svm/asid.h

index 1ae1c082191f03af4413a315d1aecd9b14a62916..2be3d8d6624bb8f91c39cbff5b0166b153954d39 100644 (file)
@@ -527,30 +527,26 @@ int hvm_set_cr3(unsigned long value)
 
     if ( paging_mode_hap(v->domain) )
     {
+        /* HAP mode. HAP-specific code does all the hard work. */
         v->arch.hvm_vcpu.guest_cr[3] = value;
-        hvm_update_guest_cr3(v, value);
-        goto success;
+        paging_update_cr3(v);
     }
-
-    if ( !hvm_paging_enabled(v) )
+    else if ( !hvm_paging_enabled(v) )
     {
+        /* Shadow-mode, paging disabled. Just update guest CR3 value. */
         v->arch.hvm_vcpu.guest_cr[3] = value;
-        goto success;
     }
-
-    if ( value == v->arch.hvm_vcpu.guest_cr[3] )
+    else if ( value == v->arch.hvm_vcpu.guest_cr[3] )
     {
-        /* 
-         * This is simple TLB flush, implying the guest has removed some
-         * translation or changed page attributes. Invalidate the shadow.
-         */
+        /* Shadow-mode TLB flush. Invalidate the shadow. */
         mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
         if ( mfn != pagetable_get_pfn(v->arch.guest_table) )
             goto bad_cr3;
+        paging_update_cr3(v);
     }
     else 
     {
-        /* Make a shadow. Check that the PDBR is valid first. */
+        /* Shadow-mode CR3 change. Check PDBR and then make a new shadow. */
         HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
         mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
         if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
@@ -564,11 +560,9 @@ int hvm_set_cr3(unsigned long value)
 
         v->arch.hvm_vcpu.guest_cr[3] = value;
         HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
+        paging_update_cr3(v);
     }
 
-    paging_update_cr3(v);
-
- success:
     return 1;
 
  bad_cr3:
index 33020178c7239c73269334801e19da89a4ae4924..a87197b33cd473b4a37b02c42a9f4ea632c013cc 100644 (file)
@@ -481,7 +481,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
     }
 
     paging_update_paging_modes(v);
-    svm_asid_g_update_paging(v);
 
     return 0;
  
@@ -1680,10 +1679,7 @@ static int svm_set_cr0(unsigned long value)
         vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP;
 
     if ( (value ^ old_value) & X86_CR0_PG )
-    {
         paging_update_paging_modes(v);
-        svm_asid_g_update_paging(v);
-    }
 
     return 1;
 }
@@ -1770,8 +1766,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
             v->arch.hvm_vcpu.guest_cr[4] = value;
             vmcb->cr4 = value | (HVM_CR4_HOST_MASK & ~X86_CR4_PAE);
             paging_update_paging_modes(v);
-            /* signal paging update to ASID handler */
-            svm_asid_g_update_paging (v);
             break;
         }
 
@@ -1796,8 +1790,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
                 if ( old_base_mfn )
                     put_page(mfn_to_page(old_base_mfn));
                 paging_update_paging_modes(v);
-                /* signal paging update to ASID handler */
-                svm_asid_g_update_paging (v);
 
                 HVM_DBG_LOG(DBG_LEVEL_VMMU, 
                             "Update CR3 value = %lx, mfn = %lx",
@@ -1821,11 +1813,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
          * all TLB entries except global entries.
          */
         if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
-        {
             paging_update_paging_modes(v);
-            /* signal paging update to ASID handler */
-            svm_asid_g_update_paging (v);
-        }
         break;
 
     case 8:
@@ -2206,8 +2194,7 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
     HVMTRACE_3D(INVLPG, v, (invlpga?1:0), g_vaddr, (invlpga?regs->ecx:0));
 
     paging_invlpg(v, g_vaddr);
-    /* signal invplg to ASID handler */
-    svm_asid_g_invlpg (v, g_vaddr);
+    svm_asid_g_invlpg(v, g_vaddr);
 }
 
 
index 1623b80204424226dee23f4d961128a34ce529a8..df61d581626ac2226f3497118222769786eee915 100644 (file)
@@ -603,38 +603,22 @@ static int hap_invlpg(struct vcpu *v, unsigned long va)
     return 0;
 }
 
-/*
- * HAP guests do not need to take any action on CR3 writes (they are still
- * intercepted, so that Xen's copy of the guest's CR3 can be kept in sync.)
- */
 static void hap_update_cr3(struct vcpu *v, int do_locking)
 {
+    hvm_update_guest_cr3(v, v->arch.hvm_vcpu.guest_cr[3]);
 }
 
 static void hap_update_paging_modes(struct vcpu *v)
 {
-    struct domain *d;
+    struct domain *d = v->domain;
 
-    d = v->domain;
     hap_lock(d);
 
-    /* update guest paging mode. Note that we rely on hvm functions to detect
-     * guest's paging mode. So, make sure the shadow registers (CR0, CR4, EFER)
-     * reflect guest's status correctly.
-     */
-    if ( hvm_paging_enabled(v) )
-    {
-        if ( hvm_long_mode_enabled(v) )
-            v->arch.paging.mode = &hap_paging_long_mode;
-        else if ( hvm_pae_enabled(v) )
-            v->arch.paging.mode = &hap_paging_pae_mode;
-        else
-            v->arch.paging.mode = &hap_paging_protected_mode;
-    }
-    else
-    {
-        v->arch.paging.mode = &hap_paging_real_mode;
-    }
+    v->arch.paging.mode =
+        !hvm_paging_enabled(v)   ? &hap_paging_real_mode :
+        hvm_long_mode_enabled(v) ? &hap_paging_long_mode :
+        hvm_pae_enabled(v)       ? &hap_paging_pae_mode  :
+                                   &hap_paging_protected_mode;
 
     v->arch.paging.translate_enabled = hvm_paging_enabled(v);
 
@@ -643,8 +627,12 @@ static void hap_update_paging_modes(struct vcpu *v)
         mfn_t mmfn = hap_make_monitor_table(v);
         v->arch.monitor_table = pagetable_from_mfn(mmfn);
         make_cr3(v, mfn_x(mmfn));
+        hvm_update_host_cr3(v);
     }
 
+    /* CR3 is effectively updated by a mode change. Flush ASIDs, etc. */
+    hvm_update_guest_cr3(v, v->arch.hvm_vcpu.guest_cr[3]);
+
     hap_unlock(d);
 }
 
index c4f23279cbb5a35d1647ad73ddad5e14e94b3f6f..1b679d05e4c9655d600dda33c109be358f868fed 100644 (file)
@@ -32,11 +32,6 @@ void svm_asid_init_vcpu(struct vcpu *v);
 void svm_asid_inv_asid(struct vcpu *v);
 void svm_asid_inc_generation(void);
 
-static inline void svm_asid_g_update_paging(struct vcpu *v)
-{
-    svm_asid_inv_asid(v);
-}
-
 static inline void svm_asid_g_invlpg(struct vcpu *v, unsigned long g_vaddr)
 {
 #if 0